/**
Copyright 2010, David Keyes.  All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may 
not use this file except in compliance with the License. You may obtain
a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0 

Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an "AS IS" BASIS, 
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and 
limitations under the License. 

*/
package com.keyes.license;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;



/**
 * Class that provides functionality for validating the purchase of applications on the Android Market.  Once
 * applications' purchase state has been determined this component takes care of licensing the application.
 * 
 * Application permissions required to use the LicenseManager include:
 * 
 * <ul>
 * <li> android.permission.INTERNET </li>
 * <li> android.permission.GET_ACCOUNTS </li>
 * <li> android.permission.USE_CREDENTIALS </li>
 * </ul>
 * 
 * @author dkeyes
 *
 */
public class LicenseManager {
  
  static {
    
    try {
      Object o = LicenseManagerImpl.class.newInstance();
      o.hashCode();
    } catch(Throwable t) {
      Log.d("", ""+t);
    }
  }
  
  public static final int LICENSE_CONFIRMED = 1;
  public static final int UNLICENSED  = 0;
  public static final int LICENSE_STATE_UNKNOWN = -1;
  
  protected static final String MSG_DIALOG_TITLE_LICENSE_CHECK = "Licensing Application";
  protected static String mMsgDialogTitle_LicenseCheck = MSG_DIALOG_TITLE_LICENSE_CHECK;

  protected static final String MSG_DIALOG_STATUS_AUTHENTICATE = "Authenticating...";
  protected static String mMsgDialogStatus_Authenticate = MSG_DIALOG_STATUS_AUTHENTICATE;
  
  protected static final String MSG_DIALOG_STATUS_VALIDATE_PURCHASE = "Verifying purchase...";
  protected static String mMsgDialogStatus_ValidatePurchase = MSG_DIALOG_STATUS_VALIDATE_PURCHASE;
  
  protected static final String MSG_DIALOG_STATUS_INSTALLING_LICENSE = "Generating license...";
  protected static String mMsgDialogStatus_InstallingLicense = MSG_DIALOG_STATUS_INSTALLING_LICENSE;
  
  protected static final String MSG_DIALOG_STATUS_FINISHED = "Success!";
  protected static String mMsgDialogStatus_Finished = MSG_DIALOG_STATUS_FINISHED;
  
  protected static final String MSG_DIALOG_STATUS_NOT_AUTHORIZED = "Purchase verification failed.";
  protected static String mMsgDialogStatus_NotAuthorized = MSG_DIALOG_STATUS_NOT_AUTHORIZED;
  
  protected static final String MSG_DIALOG_TITLE_INTRO = "License Verification";
  protected static String mMsgDialogTitle_Intro = MSG_DIALOG_TITLE_INTRO;

  protected static final String MSG_DIALOG_BODY_INTRO = "Your license to run this application will now be verified.  This requires a call to Google APIs using your credentials to validate your purchase from the Android Market.  Thanks for your support, and enjoy!";
  protected static String mMsgDialogBody_Intro = MSG_DIALOG_BODY_INTRO;
  
  protected static final String MSG_DIALOG_INTRO_CANCEL = "Cancel";
  protected static String mMsgDialogButton_Intro_Cancel = MSG_DIALOG_INTRO_CANCEL;
  
  protected static final String MSG_DIALOG_INTRO_NEXT= " Next > ";
  protected static String mMsgDialogButton_Intro_Next = MSG_DIALOG_INTRO_NEXT;
  
  protected static final String MSG_DIALOG_TITLE_LICENSE_FAILURE = "License Validation Error";
  protected static String mMsgDialogTitle_LicenseFailure = MSG_DIALOG_TITLE_LICENSE_FAILURE;
  
  protected static final String MSG_DIALOG_BODY_LICENSE_FAILURE = "We have so far been unable to validate your purchase of this application. If you did not buy this app from the Android market, you may do so by clicking the link below.  Thanks for supporting hard-working Android developers!";
  protected static String mMsgDialogBody_LicenseFailure = MSG_DIALOG_BODY_LICENSE_FAILURE;
  
  protected static final String MSG_DIALOG_BUTTON_LICENSE_FAILURE_EXIT = "Exit";
  protected static String mMsgDialogButton_LicenseFailure_Exit = MSG_DIALOG_BUTTON_LICENSE_FAILURE_EXIT;
  
  protected static final String MSG_DIALOG_BUTTON_LICENSE_FAILURE_CONTINUE = "Continue";
  protected static String mMsgDialogButton_LicenseFailure_Continue = MSG_DIALOG_BUTTON_LICENSE_FAILURE_CONTINUE;
  
  protected static final String MSG_DIALOG_BUTTON_LICENSE_FAILURE_BUY = "Purchase App!";
  protected static String mMsgDialogButton_LicenseFailure_Buy = MSG_DIALOG_BUTTON_LICENSE_FAILURE_BUY;

  public final static int FAILURE_BEHAVIOR_INVITE = 0x1;
  public final static int FAILURE_BEHAVIOR_IGNORE = 0x2;
  public final static int FAILURE_BEHAVIOR_BLOCK  = 0x4;
  public final static int FAILURE_BEHAVIOR_NAG    = 0x8;
  
  protected static class LicensePolicy {
    private final static int DEFAULT_MAX_FAILURES = 5;
    private final static int DEFAULT_FAILURE_DELAY = 15000;  // 15 secs
    
    public int              maxFailures     = DEFAULT_MAX_FAILURES;    // failures before the app will invoke the failure behavior policy
    public int              failureBehavior = FAILURE_BEHAVIOR_INVITE | FAILURE_BEHAVIOR_NAG;
    public int              failureDelay    = DEFAULT_FAILURE_DELAY;   // msecs to delay before allowing the user to continue after max failures reached
  }


  /**
   * Check the license for the application to which pActivity belongs.  
   * 
   * @param pActivity an activity in the market application that is to be validated and licensed
   */
  public synchronized void checkLicense(Activity pActivity){
    LicenseManagerImpl.checkLicense(pActivity);
  }
  
  /**
   * Check the license for the application to which pActivity belongs.  

   * @param pActivity an activity in the market application that is to be validated and licensed
   * @param pCallback where to deliver notification of license state once it is identified
   */
  public synchronized void checkLicense(Activity pActivity, CheckLicenseCallback pCallback){
    LicenseManagerImpl.checkLicense(pActivity, pCallback);
  }  
  
  /**
   * Check the license for the application to which pActivity belongs.  Also allows the user to specify whether any 
   * of the application dialogs should be displayed via pDisplayUI.
   *   
   * @param pAppLicense the developer license authorizing the use of the license manager for a specific application
   * @param pActivity an activity in the market application that is to be validated and licensed
   * @param pDisplayUI if true, displays dialogs informing user license state, false silently checks license state
   */
  public synchronized void checkLicense(Activity pActivity, boolean pDisplayUI){
    LicenseManagerImpl.checkLicense(pActivity, pDisplayUI);
  }    
  
  /**
   * Check the license for the application to which pActivity belongs.  Also allows the user to specify whether any 
   * of the application dialogs should be displayed via pDisplayUI.

   * 
   * @param pActivity an activity in the market application that is to be validated and licensed
   * @param pDisplayUI if true, displays dialogs informing user license state, false silently checks license state
   * @param pCallback where to deliver notification of license state once it is identified
   */
  public synchronized void checkLicense(final Activity pActivity, final boolean pDisplayUI, final CheckLicenseCallback pCallback){

    LicenseManagerImpl.checkLicense(pActivity, pDisplayUI, pCallback);
  }
  
  /**
   * Provides a mechanism for the developer to control the behavior of the license manager.  The failure policy is controlled
   * by specifying a bit mask, indicating the desired behavior.  Possible values and their meanings:
   * 
   * <ul>
   * <li> FAILURE_BEHAVIOR_IGNORE - all licensing failures are ignored, and the user is not notified.  Use this when all failures will be handled in a callback.</li>
   * <li> FAILURE_BEHAVIOR_INVITE - when the failure threshold pMaxFailures has been passed, invite the user to purchase the application. </li>
   * <li> FAILURE_BEHAVIOR_BLOCK  - exit of the failure notification dialog forces the app to close.  This effectively blocks the user from using the app once pMaxFailures threshold has been passed.</li>
   * <li> FAILURE_BEHAVIOR_NAG    - once the failure threshold pMaxFailures has been passed, this flag indicates that the "exit" or "continue" buttons of the failure dialog will be disabled for the amount of time specified in pFailureDelay.  This forces ("nags") the user to read the screen.</li>   
   * </ul>
   * 
   * @param pMaxFailures the number of license check failures to allow before executing the failure policy defined by pFailurePolicy
   * @param pFailurePolicy the behavior of the license manager after pMaxFailures licensing failures have occurred
   * @param pFailureDelay the length of time to display the "nag" message to the user before enabling the button that allows the user to exit the license failure dialog. 
   */
  public void setValidationPolicy(
      int pMaxFailures,
      int pFailurePolicy,
      int pFailureDelay
  ){
    LicenseManagerImpl.setValidationPolicy(pMaxFailures, pFailurePolicy, pFailureDelay);
  }
  
  /**
   * This method allows an application to customize the strings that are to be used in the various dialogs displayed
   * by the license manager.  Applications can (and should) localize these messages using the normal mechanisms 
   * of the Android platform.
   * 
   * Example usage in an Activity's onCreate method:
   * 
   * Bundle lBundle = new Bundle();
   * lBundle.putString("message.dialog.intro.title", getStringResource(R.strings.myIntroDialogTitle) );
   * ...
   * LicenseManager.setMessages(lBundle);
   * 
   * A full list of the customizable message keys include:
   * 
   * <ul>
   * <li> message.dialog.intro.title </li>
   * <li> message.dialog.intro.body </li>
   * <li> message.dialog.intro.button.cancel </li>
   * <li> message.dialog.intro.button.next </li>
   * 
   * <li> message.dialog.licenseCheck.title </li>
   * <li> message.dialog.licenseCheck.status.authenticate </li>
   * <li> message.dialog.licenseCheck.status.validatePurchase </li>
   * <li> message.dialog.licenseCheck.status.installingLicense </li>
   * <li> message.dialog.licenseCheck.status.finished </li>
   * <li> message.dialog.licenseCheck.status.notAuthorized </li>
   * 
   * <li> message.dialog.licenseFailure.title </li>
   * <li> message.dialog.licenseFailure.body </li>
   * <li> message.dialog.licenseFailure.button.buy </li>
   * <li> message.dialog.licenseFailure.button.exit </li>
   * <li> message.dialog.licenseFailure.button.continue </li>
   * </ul>
   * 
   * @param pMessagesBundle bundle containing the strings to use in the licensing component
   */
  public void setMessages(Bundle pMessagesBundle){
    LicenseManagerImpl.setMessages(pMessagesBundle);
  }

  
  
}
